<?php

final class Front {

    private $registry;
    public function __get($key) {
        return $this->registry->get($key);
    }

    public function __set($key, $value) {
        $this->registry->set($key, $value);
    }

    public function __construct() {
        $this->registry = Registry::getInstance();
    }
    
    public function handleRequest($action) {
        //1 Создаем новый объект-контекст
        $request_context = new RequestContext();
        //2 Создаем ссылку на текущий контроллер страницы
        $controller = null;
        do {
            $current_action = $action;
            $request_context->setCurrentAction($current_action);
            //3 Получаем ссылки на контроллеры блоков и главный контроллер
            list($controller, $block_controllers) = $this->dispatch($request_context);
        }
        while($action = $this->getNextAction($request_context));

        //4 Собирае html со всех блоков
        $htmls = array();
        foreach ($block_controllers as $key => $value) {
                $htmls[$key] = $value->getHTMLArray($request_context);
        }

        $this->registry->themeunit->add(array('blocks'=>$htmls));
        return $request_context;
    }
    
    
    function getNextAction(RequestContext $context) {
        $controller = $context->getCurrentController();
        if ($forward_action = $context->getForwardAction()) {
            $context->unsetForwardAction();
            $action = $forward_action;
        } elseif ($controller->getStatus() != OK) {
            $action = $context->getErrorAction();
            $action->setArgs(array($controller->getStatus()));
            $context->unsetForwardAction();
        } else {
            $action = false;
        }
        return $action;
    }
    
    public function dispatch($request_context) {
        $action = $request_context->getCurrentAction();
        $class = $action->getClass();
        $controller = ModuleFactory::create($class, $request_context);
        $request_context->setCurrentController($controller);
        
        $allowed_blocks = $controller->getAllowedBlocks($action->getMethod());
        $block_controllers = array();
        foreach ($allowed_blocks as $key => $value) {
            $block = (new $this->blocks[$value]['main-controller']($request_context));
            $block->onCreatePage($request_context);
            $block_controllers[] = $block;
        }
        $controller->onCreatePage($request_context);
        
        $res = $this->registry->form_manager->invokePOSTHandlers($request_context);
        if ($res instanceof Action) {
            $request_context->setForwardAction($res);
            return $controller;
        }
        $this->registry->form_manager->unsetHandlers();
        
        $res = true;
        if(method_exists($controller, $action->getMethod()))
        {
            if (method_exists($controller, $action->getMethod() . '_arguments_checker')) {
                $res = $controller->{$action->getMethod() . '_arguments_checker'}($request_context);
                if (is_numeric($res)) {
                    $controller->setStatus($res);
                }
                elseif($res instanceof Action)
                {
                    $request_context->setForwardAction($res);
                }
            }
            if ($res) {
                $res = $controller->{$action->getMethod()}($request_context);
                if (is_numeric($res)) {
                    $controller->setStatus($res);
                }
                elseif($res instanceof Action)
                {
                    $request_context->setForwardAction($res);
                }
            }
        }
        return array($controller, $block_controllers);
    }
//    public function dispatch($action) {
//        
//        $this->current_action = $action;
//        
//        //1. Создаем объект класса указанного в Action
//        if (!isset($this->current_object) || (isset($this->current_object) && get_class($this->current_object) != $action->getClass())) {
//            $class = $action->getClass();
//            $this->current_object = ModuleFactory::create($class, false);
//            $this->current_object->onCreatePage($action->getArgs());
//        }
//        
//        //2. Получаем список блоков
//        $allowed_blocks = $this->current_object->getAllowedBlocks($action->getMethod()); 
//        $blocksobjects = array();
//        
//        //3. создаем массив объектов-блоков
//        foreach ($allowed_blocks as $key => $value) {
//                $blocksobjects[$value] = (new $this->blocks[$value]['main-controller'](null,$action));
//        }
//        //4. Вызываем обработку POST
//        if($action->isNeedPostProcessing())
//        {
//            
//            $new_action = $this->registry->form_manager->activatePOSTHandlers();
//            $this->registry->form_manager->unsetHandlers();
//            if($new_action instanceof Action) 
//            {
//                return $this->dispatch($new_action); 
//            }
//        }
//        //5. вызываем глвный метод основного контроллера,
//        //   если он вернул ошибку, т.е. не OK,
//        //   повторяем вызов этой функции заменив action на error
//        
//        if(method_exists($this->current_object, $action->getMethod()))
//        {
//            $args = $action->getArgs();
//            $result_of_checking_args = true;
//            if(method_exists($this->current_object, $action->getMethod().'_arguments_checker'))
//            {
//                $result_of_checking_args = $this->current_object->{$action->getMethod().'_arguments_checker'}($args);
//            }
//            if($result_of_checking_args instanceof Action)
//            {
//                $result_of_checking_args->resetNeedPostProcessing();
//                return $this->dispatch($result_of_checking_args);
//            }
//            elseif($result_of_checking_args!=VALIDATION_ACCEPTED)
//            {
//                return $this->dispatch(ActionFactory::createError(NOT_FOUND));
//            }
//            $result = $this->current_object->{$action->getMethod()}($args);
//            if($result instanceof Action)
//            {
//                $result->resetNeedPostProcessing();
//                return $this->dispatch($result);
//            }
//            elseif($result!=OK)
//            {
//                return $this->dispatch(ActionFactory::createError($result));
//            }
//        }
//        else
//            return $this->dispatch(ActionFactory::createError(NOT_FOUND));  
//
//
//        //6. вызываем методы возвращающие html блоков
//        $htmls = array();
//        foreach ($blocksobjects as $key => $value) {
//                $htmls[$key] = $value->getHTMLArray();
//        }
//
//        $this->registry->themeunit->add(array('blocks'=>$htmls));
//        
//        return $action;
//    }
}

?>